﻿using System;
using System.Web.UI;

namespace N2.ComponentModel
{
	/// <summary>
	/// Generic container for a System.Type property.
	/// After construction, should be used like this:
	/// <example>
	///		private TypePropertyHolder TypeHolder;
	///		
	///		public Type MyType {
	///			get { return this.TypeHolder.Value; }
	///			set { this.TypeHolder.Value = value; }
	///		}
	/// </example>
	/// </summary>
	public abstract class TypePropertyHolder
	{
		protected readonly Type DefaultValue;

		protected TypePropertyHolder(Type defaultValue)
		{
			this.DefaultValue = defaultValue;
		}

		public Type Value {
			get {
				return
					string.IsNullOrEmpty(this.ValueBackingStore)
						? this.DefaultValue
						: Type.GetType(this.ValueBackingStore, false)
							?? this.DefaultValue;
			}
			set { this.ValueBackingStore = null != value
				? value.AssemblyQualifiedName
				: null; }
		}

		protected abstract string ValueBackingStore { get; set; }
	}

	//An example implementation..
	public sealed class PersistingTypePropertyHolder : TypePropertyHolder
	{
		#region Fields
		
		readonly ContentItem CurrentItem;
		readonly string DetailName;
		
		#endregion Fields

		#region Constructor

		public PersistingTypePropertyHolder(ContentItem item, string detailName, Type defaultValue)
			: base(defaultValue)
		{
			this.CurrentItem = item;
			this.DetailName = detailName;
		}

		#endregion Constructor

		#region Properties

		protected override string ValueBackingStore {
			get {
				return (string)this.CurrentItem.GetDetail(this.DetailName);
			}
			set {
				this.CurrentItem[this.DetailName] = value;
			}
		}

		#endregion Properties
	}

	public sealed class ViewStateTypePropertyHolder : TypePropertyHolder
	{
		#region Fields

		readonly StateBag m_vs;

		#endregion Fields

		#region Constructors

		public ViewStateTypePropertyHolder(StateBag viewState):base(null)
		{
			this.m_vs = viewState;
		}
		
		#endregion Constructors

		protected override string ValueBackingStore {
			get { return (string)this.m_vs["TypeName"]; }
			set { this.m_vs["TypeName"] = value; }
		}
	}
}
